/**
 * 
 */
package com.android.fxcontacts;

import com.android.internal.telephony.FxTelephony;
import com.android.internal.telephony.ITelephony;

import android.app.Activity;
import android.app.TabActivity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import android.provider.CallLog.Calls;
import android.util.Log;
import android.view.Window;
import android.widget.TabHost;

/**
 * The dialer activity that has one tab with the virtual 12key
 * dialer, a tab with recent calls in it, a tab with the contacts and
 * a tab with the favorite. This is the container and the tabs are
 * embedded using intents.
 * The dialer tab's title is 'phone', a more common name (see strings.xml).
 */
public class DialtactsActivity extends TabActivity implements
		TabHost.OnTabChangeListener
{
	private static final String TAG = "Dailtacts";
	private static final String FAVORITES_ENTRY_COMPONENT = "com.android.contacts.DialtactsFavoritesEntryActivity";

	/** Opens the Contacts app in the state the user has last set it to */
	private static final String CONTACTS_LAUNCH_ACTIVITY = "com.android.contacts.ContactsLaunchActivity";

	private static final int TAB_INDEX_DIALER = 0;
	private static final int TAB_INDEX_CALL_LOG = 1;
	private static final int TAB_INDEX_CONTACTS = 2;
	private static final int TAB_INDEX_FAVORITES = 3;

	static final String EXTRA_IGNORE_STATE = "ignore-state";

	/** Name of the dialtacts shared preferences */
	static final String PREFS_DIALTACTS = "dialtacts";
	/**
	 * If true, when handling the contacts intent the favorites tab will be
	 * shown instead
	 */
	static final String PREF_FAVORITES_AS_CONTACTS = "favorites_as_contacts";
	static final boolean PREF_FAVORITES_AS_CONTACTS_DEFAULT = false;

	/** Last manually selected tab index */
	private static final String PREF_LAST_MANUALLY_SELECTED_TAB = "last_manually_selected_tab";
	private static final int PREF_LAST_MANUALLY_SELECTED_TAB_DEFAULT = TAB_INDEX_DIALER;

	private TabHost mTabHost;
	private String mFilterText;
	private Uri mDialUri;

	/**
	 * The index of the tab that has last been manually selected (the user
	 * clicked on a tab).
	 * This value does not keep track of programmatically set Tabs (e.g. Call
	 * Log after a Call)
	 */
	private int mLastManuallySelectedTab;

	@Override
	protected void onCreate(Bundle icicle)
	{
		super.onCreate(icicle);

		final Intent intent = getIntent();
		fixIntent(intent);

		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.dialer_activity);

		mTabHost = getTabHost();
		mTabHost.setOnTabChangedListener(this);

		// Setup the tabs
		setupDialerTab();
		setupCallLogTab();
		setupContactsTab();
		setupFavoritesTab();

		// Load the last manually loaded tab
		final SharedPreferences prefs = getSharedPreferences(PREFS_DIALTACTS,
				MODE_PRIVATE);
		mLastManuallySelectedTab = prefs.getInt(
				PREF_LAST_MANUALLY_SELECTED_TAB,
				PREF_LAST_MANUALLY_SELECTED_TAB_DEFAULT);

		setCurrentTab(intent);

		if (intent.getAction().equals(ContactsActivity.FILTER_CONTACTS_ACTION)
				&& icicle == null)
		{
			setupFilterText(intent);
		}
	}

	@Override
	protected void onPause()
	{
		super.onPause();

		final int currentTabIndex = mTabHost.getCurrentTab();
		final SharedPreferences.Editor editor = getSharedPreferences(
				PREFS_DIALTACTS, MODE_PRIVATE).edit();
		if (currentTabIndex == TAB_INDEX_CONTACTS
				|| currentTabIndex == TAB_INDEX_FAVORITES)
		{
			editor.putBoolean(PREF_FAVORITES_AS_CONTACTS,
					currentTabIndex == TAB_INDEX_FAVORITES);
		}
		editor
				.putInt(PREF_LAST_MANUALLY_SELECTED_TAB,
						mLastManuallySelectedTab);

		editor.commit();
	}

	private void fixIntent(Intent intent)
	{
		// This should be cleaned up: the call key used to send an Intent
		// that just said to go to the recent calls list. It now sends this
		// abstract action, but this class hasn't been rewritten to deal with
		// it.
		if (Intent.ACTION_CALL_BUTTON.equals(intent.getAction()))
		{
			intent.setDataAndType(Calls.CONTENT_URI, Calls.CONTENT_TYPE);
			intent.putExtra("call_key", true);
			setIntent(intent);
		}
	}

	private void setupCallLogTab()
	{
		// Force the class since overriding tab entries doesn't work
		Intent intent = new Intent("com.android.phone.action.RECENT_CALLS");
		intent.setClass(this, RecentCallsListActivity.class);

		mTabHost.addTab(mTabHost.newTabSpec("call_log").setIndicator(
				getString(R.string.recentCallsIconLabel),
				getResources().getDrawable(R.drawable.ic_tab_recent))
				.setContent(intent));
	}

	private void setupDialerTab()
	{
		Intent intent = new Intent("com.android.phone.action.TOUCH_DIALER");
		intent.setClass(this, TwelveKeyDialer.class);

		mTabHost.addTab(mTabHost.newTabSpec("dialer").setIndicator(
				getString(R.string.dialerIconLabel),
				getResources().getDrawable(R.drawable.ic_tab_dialer))
				.setContent(intent));
	}

	private void setupContactsTab()
	{
		Intent intent = new Intent(ContactsActivity.LIST_DEFAULT);
		intent.setClass(this, ContactsActivity.class);

		mTabHost.addTab(mTabHost.newTabSpec("contacts").setIndicator(
				getText(R.string.contactsIconLabel),
				getResources().getDrawable(R.drawable.ic_tab_contacts))
				.setContent(intent));
	}

	private void setupFavoritesTab()
	{
		Intent intent = new Intent(ContactsActivity.LIST_STREQUENT_ACTION);
		intent.setClass(this, ContactsActivity.class);

		mTabHost.addTab(mTabHost.newTabSpec("favorites").setIndicator(
				getString(R.string.contactsFavoritesLabel),
				getResources().getDrawable(R.drawable.ic_tab_starred))
				.setContent(intent));
	}

	/**
	 * Returns true if the intent is due to hitting the green send key while in
	 * a call.
	 * 
	 * @param intent
	 *            the intent that launched this activity
	 * @param recentCallsRequest
	 *            true if the intent is requesting to view recent calls
	 * @return true if the intent is due to hitting the green send key while in
	 *         a call
	 */
	private boolean isSendKeyWhileInCall(final Intent intent,
			final boolean recentCallsRequest)
	{
		// If there is a call in progress go to the call screen
		if (recentCallsRequest)
		{
			final boolean callKey = intent.getBooleanExtra("call_key", false);

			try
			{
				// ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
				// get ITelephony instance
				ITelephony phone = FxTelephony.getITelelephony(this);
				
				if (callKey && phone != null && phone.showCallScreen())
				{
					return true;
				}
			} catch (RemoteException e)
			{
				Log.e(TAG, "Failed to handle send while in call", e);
			}
		}

		return false;
	}

	/**
	 * Sets the current tab based on the intent's request type
	 * 
	 * @param intent
	 *            Intent that contains information about which tab should be
	 *            selected
	 */
	private void setCurrentTab(Intent intent)
	{
		// If we got here by hitting send and we're in call forward along to the
		// in-call activity
		final boolean recentCallsRequest = Calls.CONTENT_TYPE.equals(intent
				.getType());
		if (isSendKeyWhileInCall(intent, recentCallsRequest))
		{
			finish();
			return;
		}

		// Dismiss menu provided by any children activities
		Activity activity = getLocalActivityManager().getActivity(
				mTabHost.getCurrentTabTag());
		if (activity != null)
		{
			activity.closeOptionsMenu();
		}

		// Tell the children activities that they should ignore any possible
		// saved
		// state and instead reload their state from the parent's intent
		intent.putExtra(EXTRA_IGNORE_STATE, true);

		// Remember the old manually selected tab index so that it can be
		// restored if it is
		// overwritten by one of the programmatic tab selections
		final int savedTabIndex = mLastManuallySelectedTab;

		// Choose the tab based on the inbound intent
		String componentName = intent.getComponent().getClassName();
		if (getClass().getName().equals(componentName))
		{
			if (recentCallsRequest)
			{
				mTabHost.setCurrentTab(TAB_INDEX_CALL_LOG);
			} else
			{
				mTabHost.setCurrentTab(TAB_INDEX_DIALER);
			}
		} else if (FAVORITES_ENTRY_COMPONENT.equals(componentName))
		{
			mTabHost.setCurrentTab(TAB_INDEX_FAVORITES);
		} else if (CONTACTS_LAUNCH_ACTIVITY.equals(componentName))
		{
			mTabHost.setCurrentTab(mLastManuallySelectedTab);
		} else
		{
			SharedPreferences prefs = getSharedPreferences(PREFS_DIALTACTS,
					MODE_PRIVATE);
			boolean favoritesAsContacts = prefs.getBoolean(
					PREF_FAVORITES_AS_CONTACTS,
					PREF_FAVORITES_AS_CONTACTS_DEFAULT);
			if (favoritesAsContacts)
			{
				mTabHost.setCurrentTab(TAB_INDEX_FAVORITES);
			} else
			{
				mTabHost.setCurrentTab(TAB_INDEX_CONTACTS);
			}
		}

		// Restore to the previous manual selection
		mLastManuallySelectedTab = savedTabIndex;

		// Tell the children activities that they should honor their saved
		// states
		// instead of the state from the parent's intent
		intent.putExtra(EXTRA_IGNORE_STATE, false);
	}

	@Override
	public void onNewIntent(Intent newIntent)
	{
		setIntent(newIntent);
		fixIntent(newIntent);
		setCurrentTab(newIntent);
		final String action = newIntent.getAction();
		if (action.equals(ContactsActivity.FILTER_CONTACTS_ACTION))
		{
			setupFilterText(newIntent);
		} else if (isDialIntent(newIntent))
		{
			setupDialUri(newIntent);
		}
	}

	/**
	 * Returns true if the given intent contains a phone number to populate the
	 * dialer with
	 */
	private boolean isDialIntent(Intent intent)
	{
		final String action = intent.getAction();
		if (Intent.ACTION_DIAL.equals(action))
		{
			return true;
		}
		if (Intent.ACTION_VIEW.equals(action))
		{
			final Uri data = intent.getData();
			if (data != null && "tel".equals(data.getScheme()))
			{
				return true;
			}
		}
		return false;
	}

	/**
	 * Retrieves the filter text stored in {@link #setupFilterText(Intent)}.
	 * This text originally came from a FILTER_CONTACTS_ACTION intent received
	 * by this activity. The stored text will then be cleared after after this
	 * method returns.
	 * 
	 * @return The stored filter text
	 */
	public String getAndClearFilterText()
	{
		String filterText = mFilterText;
		mFilterText = null;
		return filterText;
	}

	/**
	 * Stores the filter text associated with a FILTER_CONTACTS_ACTION intent.
	 * This is so child activities can check if they are supposed to display a
	 * filter.
	 * 
	 * @param intent
	 *            The intent received in {@link #onNewIntent(Intent)}
	 */
	private void setupFilterText(Intent intent)
	{
		// If the intent was relaunched from history, don't apply the filter
		// text.
		if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0)
		{
			return;
		}
		String filter = intent
				.getStringExtra(ContactsActivity.FILTER_TEXT_EXTRA_KEY);
		if (filter != null && filter.length() > 0)
		{
			mFilterText = filter;
		}
	}

	/**
	 * Retrieves the uri stored in {@link #setupDialUri(Intent)}. This uri
	 * originally came from a dial intent received by this activity. The stored
	 * uri will then be cleared after after this method returns.
	 * 
	 * @return The stored uri
	 */
	public Uri getAndClearDialUri()
	{
		Uri dialUri = mDialUri;
		mDialUri = null;
		return dialUri;
	}

	/**
	 * Stores the uri associated with a dial intent. This is so child activities
	 * can
	 * check if they are supposed to display new dial info.
	 * 
	 * @param intent
	 *            The intent received in {@link #onNewIntent(Intent)}
	 */
	private void setupDialUri(Intent intent)
	{
		// If the intent was relaunched from history, don't reapply the intent.
		if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0)
		{
			return;
		}
		mDialUri = intent.getData();
	}

	@Override
	public void onBackPressed()
	{
		if (isTaskRoot())
		{
			// Instead of stopping, simply push this to the back of the stack.
			// This is only done when running at the top of the stack;
			// otherwise, we have been launched by someone else so need to
			// allow the user to go back to the caller.
			moveTaskToBack(false);
		} else
		{
			super.onBackPressed();
		}
	}

	/** {@inheritDoc} */
	public void onTabChanged(String tabId)
	{
		// Because we're using Activities as our tab children, we trigger
		// onWindowFocusChanged() to let them know when they're active. This may
		// seem to duplicate the purpose of onResume(), but it's needed because
		// onResume() can't reliably check if a keyguard is active.
		Activity activity = getLocalActivityManager().getActivity(tabId);
		if (activity != null)
		{
			activity.onWindowFocusChanged(true);
		}

		// Remember this tab index. This function is also called, if the tab is
		// set automatically
		// in which case the setter (setCurrentTab) has to set this to its old
		// value afterwards
		mLastManuallySelectedTab = mTabHost.getCurrentTab();
	}

}
